package com.zsrt.devbase.common.aspect.controller;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.zsrt.devbase.common.annotation.HandleEntity;
import com.zsrt.devbase.common.utils.ConstantDefine;
import com.zsrt.devbase.common.utils.DateUtil;
import com.zsrt.devbase.common.utils.ShiroUtil;
import com.zsrt.devbase.dto.BaseDTO;

/**
 * 处理实体切面 
 * 1.处理空串 
 * 2.填写创建人和创建时间 
 * 3.填写修改人和修改时间
 * 
 * @author leixin
 * @Email leixin821792669@gmail.com
 * @date 2017年5月18日 上午12:14:48
 *
 */
@Component
@Aspect
@Order(2)
public class HandleEntityAspect {

	private Logger logger = Logger.getLogger(this.getClass());

	private String[] createFieldNames = {"creator", "createTime"};
	private String[] modifyFieldNames = {"modifier", "modifyTime"};
	
	/**
	 * 切入点为所有控制层中参数包含了BaseDTO及其子类的方法
	 * @author leixin
	 * @date 2017年5月18日
	 * @param joinPoint
	 * @return
	 * @throws Throwable
	 */
	@Around("execution(* com.zsrt.devbase.controller.*.*(..)) &&(args(com.zsrt.devbase.dto.BaseDTO,..)||args(..,com.zsrt.devbase.dto.BaseDTO))")
	public Object replaceString(ProceedingJoinPoint joinPoint)
			throws Throwable {
		logger.info("开始执行HandleEntityAspect的replaceString方法");
		MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
		Method method = methodSignature.getMethod();
		HandleEntity handleEntity = method.getAnnotation(HandleEntity.class);
		// 定义需要处理的位置的三个标志
		boolean replaceEmptyString = true;
		boolean fillCreator = false;
		boolean fillModifier = false;

		if (null != handleEntity) {
			replaceEmptyString = handleEntity.replaceEmptyString();
			fillCreator = handleEntity.fillCreator();
			fillModifier = handleEntity.fillModifier();
		}
		Object[] args = joinPoint.getArgs();
		for (int i = 0; i < args.length; i++) {
			if (args[i] instanceof BaseDTO) {
				Class<? extends Object> clazz = args[i].getClass();
				// 处理空串
				try {
					if (replaceEmptyString) {
						replaceEmptyStringToNull(args[i], clazz);
						replaceEmptyStringToNull(args[i], clazz.getSuperclass());
					}
					// 自动填充创建人和创建时间
					if (fillCreator) {
						setCurrentUserAndSystemTime(args[i], createFieldNames);
					}
					// 自动填充修改人人和修改时间
					if (fillModifier) {
						setCurrentUserAndSystemTime(args[i], modifyFieldNames);
					}
				} catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					logger.error("自动填充字段信息错误");
					Map<String, Object> result = new HashMap<>();
					result.put(ConstantDefine.SYS_ERROR_KEY,ConstantDefine.SYS_ERR_MSG);
					return result;
				}
			}
		}
		return joinPoint.proceed(args);
	}

	private void replaceEmptyStringToNull(Object object,Class<? extends Object> clazz)
			throws IllegalArgumentException, IllegalAccessException {
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			String type = field.getType().getName();
			// 强制访问私有属性
			field.setAccessible(true);
			if ("java.lang.String".equals(type)) {
				String value = (String) field.get(object);
				if (value != null && "".equals(value.trim())) {
					field.set(object, null);
				}
			}
		}
	}

	private void setCurrentUserAndSystemTime(Object object, String[] fieldNames)
			throws NoSuchFieldException, IllegalArgumentException,
			IllegalAccessException {
		Class<?> superclass = object.getClass().getSuperclass();
		for (int i = 0; i < fieldNames.length; i++) {
			Field field = superclass.getDeclaredField(fieldNames[i]);
			field.setAccessible(true);
			if (fieldNames[i].contains("Time")) {
				field.set(object, DateUtil.getSystemTimeStr());
			} else {
				field.set(object, ShiroUtil.getSessionByKey(ConstantDefine.PERSONCODE_SESSION));
			}

		}
	}

}
